package de.hska.bestellverwaltung.ui;

import static de.hska.util.EjbNames.KUNDENVERWALTUNG_LOCAL_NAME;
import static de.hska.util.EjbNames.BESTELLVERWALTUNG_LOCAL_NAME;
import static de.hska.util.EjbNames.ARTIKELVERWALTUNG_LOCAL_NAME;
import static de.hska.util.WebConstants.FWD_BESTELLUNG_WARENKORB;
import static de.hska.util.WebConstants.FWD_BESTELLUNG_ABSCHICKEN;
import static de.hska.util.WebConstants.FWD_BESTELLUNG_BESTAETIGUNG;
import static de.hska.util.WebConstants.FWD_BESTELLUNG_ARTIKEL_AUSWAEHLEN;
import static de.hska.util.WebConstants.FWD_ACCESS_DENIED;
import static de.hska.admin.ui.AuthenticationUiBean.login;
import static de.hska.util.LogUtil.begin;
import static de.hska.util.LogUtil.end;
import static de.hska.util.LogUtil.endError;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.EJBAccessException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import de.hska.admin.ui.AuthenticationUiBean;
import de.hska.artikelverwaltung.Artikelverwaltung;
import de.hska.artikelverwaltung.db.Artikel;
import de.hska.bestellverwaltung.Bestellverwaltung;
import de.hska.bestellverwaltung.db.Bestellposition;
import de.hska.bestellverwaltung.db.Bestellung;
import de.hska.kundenverwaltung.Kundenverwaltung;
import de.hska.kundenverwaltung.db.Kunde;
import de.hska.kundenverwaltung.db.KundeNotFoundException;

public class BestellverwaltungUiBean {
	private static final Log LOG = LogFactory.getLog(BestellverwaltungUiBean.class);
	private static final boolean DEBUG = LOG.isDebugEnabled();
	private static final boolean TRACE = LOG.isTraceEnabled();
	
	// TODO EJB-Name ueberfluessig bei JBoss 5
	@EJB(name=BESTELLVERWALTUNG_LOCAL_NAME)
	private Bestellverwaltung bv;
	
	// TODO EJB-Name ueberfluessig bei JBoss 5
	@EJB(name=KUNDENVERWALTUNG_LOCAL_NAME)
	private Kundenverwaltung kv;
	
	// TODO EJB-Name ueberfluessig bei JBoss 5
	@EJB(name=ARTIKELVERWALTUNG_LOCAL_NAME)
	private Artikelverwaltung av;
	
	private List<Artikel> verfuegbareArtikel = null;
	private List<Artikel> ausgewaehlteArtikel = new ArrayList<Artikel>();
	
	// Der Warenkorb sollte entweder als Stateful Session Bean (und damit transient)
	// oder in der Datenbank (wie z.B. bei Amazon) verwaltet werden.
	// Damit das >>BEISPIEL<< nicht zu gross wird, wird er im Managed Bean verwaltet
	private List<Bestellposition> warenkorb = null;
	private Bestellung bestellung = null;
	
	public List<Artikel> getVerfuegbareArtikel() {
		if (verfuegbareArtikel == null)
			verfuegbareArtikel = av.findVerfuegbareArtikel();
		return verfuegbareArtikel;
	}

	public void setVerfuegbareArtikel(List<Artikel> verfuegbareArtikel) {
		this.verfuegbareArtikel = verfuegbareArtikel;
	}

	public List<Artikel> getAusgewaehlteArtikel() {
		return ausgewaehlteArtikel;
	}

	public void setAusgewaehlteArtikel(List<Artikel> ausgewaehlteArtikel) {
		this.ausgewaehlteArtikel = ausgewaehlteArtikel;
	}

	public List<Bestellposition> getWarenkorb() {
		return warenkorb;
	}

	public void setWarenkorb(List<Bestellposition> warenkorb) {
		this.warenkorb = warenkorb;
	}
	
	public Bestellung getBestellung() {
		return bestellung;
	}


	/**
	 */
	public String insertWarenkorb() {
		if (DEBUG) begin(LOG);
		
		if (warenkorb == null)
			warenkorb = new ArrayList<Bestellposition>(ausgewaehlteArtikel.size());

		for (Artikel a: ausgewaehlteArtikel) {
			// Ist der Artikel bereits im Warenkorb?
			boolean bereitsVorhanden = false;
			for (Bestellposition bp: warenkorb) {
				if (bp.getArtikel().getId().equals(a.getId())) {
					bereitsVorhanden = true;
					break;
				}
			}
			if (bereitsVorhanden == true)
				continue;
			
			final Bestellposition bp = new Bestellposition();
			bp.setArtikel(a);
			warenkorb.add(bp);
		}
		
		ausgewaehlteArtikel.clear();
		verfuegbareArtikel = null;
		
		if (DEBUG) end(LOG, warenkorb.size());
		return FWD_BESTELLUNG_WARENKORB;
	}

	/**
	 */
	public String updateWarenkorb() {
		if (DEBUG) begin(LOG);
		
		// Nur die Bestellpositionen beibehalten mit Anzahl > 0
		final List<Bestellposition> warenkorbNeu = new ArrayList<Bestellposition>(warenkorb.size());
 		for (Bestellposition bp: warenkorb) {
			if (bp.getAnzahl() > 0) {
				if (TRACE) LOG.trace(bp);
				warenkorbNeu.add(bp);
			}
		}
		
		warenkorb = warenkorbNeu;
		
		if (DEBUG) end(LOG, warenkorb);
		return FWD_BESTELLUNG_ABSCHICKEN;
	}


	/**
	 */
	public String bestellungAbschicken() {
		if (DEBUG) begin(LOG);
		
		login();

		bestellung = new Bestellung();
		bestellung.setBestellpositionen(warenkorb);

		// Kunde zuordnen
		final Kunde kunde =  findKunde();
		
		// Den gefundenen Kunden dem Warenkorb bzw. der Bestellung zuordnen
		bestellung.setKunde(kunde);
		
		// Warenkorb bzw. Bestellung abspeichern
		try {
			bestellung = bv.create(bestellung);
		}
		catch (KundeNotFoundException e) {
			// Kann nicht passieren, da der Kunde zuvor ermittelt wurde
			final IllegalStateException e2 = new IllegalStateException(e);
			endError(LOG, e);
			throw e2;
		}
		catch (EJBAccessException e) {
			endError(LOG, e);
			return FWD_ACCESS_DENIED;
		}
		
		// Zuruecksetzen
		warenkorb = null;

		if (DEBUG) end(LOG, bestellung);
		return FWD_BESTELLUNG_BESTAETIGUNG;
	}
	
	/**
	 */
	private Kunde findKunde() {
		if (DEBUG) begin(LOG);
		
		final AuthenticationUiBean auth = AuthenticationUiBean.getInstance();
		final String userName = auth.getUserName();
		
		if (userName == null) {
			// kann nicht passieren, da in save() zuerst login() und
			// dann findKunde() aufgerufen wird 
			final KundeNotFoundException e = new KundeNotFoundException();
			final IllegalStateException e2 = new IllegalStateException(e);
			endError(LOG, e.getMessage());
			throw e2;
		}
		
		Kunde kunde = null;
		try {
			kunde = kv.findKundeByUserName(userName);
		}
		catch (KundeNotFoundException e) {
			// Kann nicht passieren, da login() bereits aufgerufen wurde
			final IllegalStateException e2 = new IllegalStateException(e);
			endError(LOG, e.getMessage());
			throw e2;
		}
		
		if (DEBUG) end(LOG, kunde);
		return kunde;
	}

	/**
	 */
	public String warenkorbAendern() {
		if (DEBUG) begin(LOG);
		
		if (DEBUG) end(LOG);
		return FWD_BESTELLUNG_WARENKORB;
	}
	
	/**
	 */
	public String warenkorbLeeren() {
		if (DEBUG) begin(LOG);
		
		warenkorb = null;
		
		if (DEBUG) end(LOG);
		return FWD_BESTELLUNG_ARTIKEL_AUSWAEHLEN;
	}
}
